<!DOCTYPE html>
<html lang="en">
  <head>
    
      <title>python中muktiprocessing模块详解 :: Rennan Blog — We can exchange and study together</title>
    
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
<meta name="description" content="参考博客： https://blog.csdn.net/hlg1995/article/details/81638732
进程：通俗的来说进程相当于一个正在运行的程序，他是资源调度的最小单位
# 首先导入进程的模块import multiprocessing模块中有一个进程类Process Process的语法结构以及用法: Process([group [, target [, name [, args [, kwargs]]]]])
 group：指定进程组，目前只能使用None target：执行的目标任务名 name：进程名字 args：以元组方式给执行任务传参 kwargs：以字典方式给执行任务传参  Process创建后的实例对象常用的方法
 start()：启动子进程实例（创建子进程） join([timeout])：是否等待子进程执行结束，或等待多少秒 terminate()：不管任务是否完成，立即终止子进程  Process创建后的实例对象常用的属性
 name：当前进程的别名，默认为Process-N，N为从1开始递增的整数 pid：当前进程的pid（进程号）  获取进程的pid:
import multiprocessingimport timeimport osdef work():# 查看当前进程current_process = multiprocessing.current_process()print(&amp;quot;work:&amp;quot;, current_process)# 获取当前进程的编号print(&amp;quot;work进程编号:&amp;quot;, current_process.pid, os.getpid())# 获取父进程的编号print(&amp;quot;work父进程的编号:&amp;quot;, os.getppid())for i in range(10):print(&amp;quot;工作中....&amp;quot;)time.sleep(0.2)# 扩展： 根据进程编号杀死对应的进程os."/>
<meta name="keywords" content=""/>
<meta name="robots" content="noodp"/>
<link rel="canonical" href="/my_blog/post/proceedingblog/" />





<link rel="stylesheet" href="/my_blog/assets/style.css">


<link rel="stylesheet" href="/my_blog/style.css">


<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/my_blog/img/apple-touch-icon-144-precomposed.png">
<link rel="shortcut icon" href="/my_blog/img/favicon.png">


<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="python中muktiprocessing模块详解"/>
<meta name="twitter:description" content="multiprocessing详解"/>



<meta property="og:title" content="python中muktiprocessing模块详解" />
<meta property="og:description" content="multiprocessing详解" />
<meta property="og:type" content="article" />
<meta property="og:url" content="/my_blog/post/proceedingblog/" />
<meta property="article:published_time" content="2019-06-05T00:00:00+00:00" />
<meta property="article:modified_time" content="2019-06-05T00:00:00+00:00" /><meta property="og:site_name" content="Rennan Blog" />






  </head>
  <body class="">
    <div class="container">
      <header class="header">
  <span class="header__inner">
    <a href="/my_blog/hello/" class="logo" style="text-decoration: none;">
  
    <span class="logo__mark"><svg xmlns="http://www.w3.org/2000/svg" class="greater-icon" viewBox="0 0 44 44">
  <path fill="none" d="M15 8l14.729 14.382L15 35.367"/>
</svg>
</span>
    <span class="logo__text">Welcome To MyBlog</span>
    <span class="logo__cursor"></span>
  
</a>

    <span class="header__right">
      
        <nav class="menu">
  <ul class="menu__inner menu__inner--desktop">
    
      
        
          <li><a href="/my_blog/resume">resume</a></li>
        
      
        
          <li><a href="/my_blog/vue">vue</a></li>
        
      
      
    
  </ul>

  <ul class="menu__inner menu__inner--mobile">
    
      
        <li><a href="/my_blog/resume">resume</a></li>
      
    
      
        <li><a href="/my_blog/vue">vue</a></li>
      
    
  </ul>
</nav>

        <span class="menu-trigger">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
            <path d="M0 0h24v24H0z" fill="none"/>
            <path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/>
          </svg>
        </span>
      
      <span class="theme-toggle">
        <svg class="theme-toggler" width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M22 41C32.4934 41 41 32.4934 41 22C41 11.5066 32.4934 3 22
  3C11.5066 3 3 11.5066 3 22C3 32.4934 11.5066 41 22 41ZM7 22C7
  13.7157 13.7157 7 22 7V37C13.7157 37 7 30.2843 7 22Z"/>
</svg>

      </span>
    </span>
  </span>
</header>


      <div class="content">
        
  
  

  <div class="post">
    <h2 class="post-title"><a href="/my_blog/post/proceedingblog/">python中muktiprocessing模块详解</a></h2>
    <div class="post-meta">
      
        <span class="post-date">
          5066-08-05
        </span>

        
          
        
      

      <span class="post-author">— Written by ren nan</span>
      
    </div>

    

    

    <div class="post-content">
      <p>参考博客：
<a href="https://blog.csdn.net/hlg1995/article/details/81638732">https://blog.csdn.net/hlg1995/article/details/81638732</a></p>
<p><strong>进程</strong>：通俗的来说进程相当于一个正在运行的程序，他是资源调度的最小单位</p>
<pre><code># 首先导入进程的模块
import multiprocessing
</code></pre><p>模块中有一个进程类Process
Process的语法结构以及用法:
Process([group [, target [, name [, args [, kwargs]]]]])</p>
<ul>
<li>group：指定进程组，目前只能使用None</li>
<li>target：执行的目标任务名</li>
<li>name：进程名字</li>
<li>args：以元组方式给执行任务传参</li>
<li>kwargs：以字典方式给执行任务传参</li>
</ul>
<p>Process创建后的实例对象常用的方法</p>
<ul>
<li>start()：启动子进程实例（创建子进程）</li>
<li>join([timeout])：是否等待子进程执行结束，或等待多少秒</li>
<li>terminate()：不管任务是否完成，立即终止子进程</li>
</ul>
<p>Process创建后的实例对象常用的属性</p>
<ul>
<li>name：当前进程的别名，默认为Process-N，N为从1开始递增的整数</li>
<li>pid：当前进程的pid（进程号）</li>
</ul>
<p>获取进程的pid:</p>
<pre><code>import multiprocessing
import time
import os
 
def work():
    # 查看当前进程
    current_process = multiprocessing.current_process()
    print(&quot;work:&quot;, current_process)
    # 获取当前进程的编号
    print(&quot;work进程编号:&quot;, current_process.pid, os.getpid())
    # 获取父进程的编号
    print(&quot;work父进程的编号:&quot;, os.getppid())
    for i in range(10):
        print(&quot;工作中....&quot;)
        time.sleep(0.2)
        # 扩展： 根据进程编号杀死对应的进程
        os.kill(os.getpid(), 9)
 
 
if __name__ == '__main__':
 
    # 查看当前进程
    current_process = multiprocessing.current_process()
    print(&quot;main:&quot;, current_process)
    # 获取当前进程的编号
    print(&quot;main进程的编号:&quot;, current_process.pid)
 
    # 创建子进程
    sub_process = multiprocessing.Process(target=work)
    # 启动进程
    sub_process.start()
 
 
    # 主进程执行打印信息操作
    for i in range(20):
        print(&quot;我在主进程中执行...&quot;)
        time.sleep(0.2)

</code></pre><p>运行结果</p>
<pre><code>
main: &lt;_MainProcess(MainProcess, started)&gt;
main进程的编号: 67264
我在主进程中执行...
work: &lt;Process(Process-1, started)&gt;
work进程编号: 71956 71956
work父进程的编号: 67264
工作中....
我在主进程中执行...
我在主进程中执行...

</code></pre><p>给子进程传递指定参数参数</p>
<pre><code>
import multiprocessing
 
 
# 显示人员信息
def show_info(name, age):
    print(name, age)
 
if __name__ == '__main__':
    # 创建子进程
    # 1. group:进程组，目前必须使用None，一般不用设置
    # 2. target:执行目标函数
    # 3. name: 进程名称
    # 4. args: 以元组方式给函数传参
    # 5. kwargs: 以字典方式给函数传参
    sub_process = multiprocessing.Process(target=show_info, name=&quot;myprocess&quot;,args=(&quot;古力娜扎&quot;, 18))
 
    # 启动进程
    sub_process.start()

</code></pre><p>运行结果：</p>
<pre><code>古力娜扎 18
</code></pre><p>进程之间不会共享变量：</p>
<pre><code>
import multiprocessing
import time
 
# 定义全局变量
my_list = list()
 
 
# 写入数据
def write_data():
    for i in range(5):
        my_list.append(i)
        time.sleep(0.2)
    print(&quot;write_data:&quot;, my_list)
 
 
# 读取数据
def read_data():
    print(my_list)
 
 
if __name__ == '__main__':
    # 创建写入数据的进程
    write_process = multiprocessing.Process(target=write_data)
    read_process = multiprocessing.Process(target=read_data)
 
    write_process.start()
    # 主进程等待写入进程执行完成以后代码 再继续往下执行
    write_process.join()
    read_process.start()

</code></pre><p>运行结果:</p>
<pre><code>
write_data: [0, 1, 2, 3, 4]
read_data: []
</code></pre><p>其实创建一个子进程就是对主进程的拷贝，进程之间相互独立，访问的全局变量都不是一个，所有进程之间不共享全局变量</p>
<h1 id="主进程等待所有子进程执行完成之后退出">主进程等待所有子进程执行完成之后退出</h1>
<pre><code>
import multiprocessing
import time
 
# 测试子进程是否执行完成以后主进程才能退出
def work():
    for i in range(10):
        print(&quot;工作中...&quot;)
        time.sleep(0.2)
 
if __name__ == '__main__':
    # 创建子进程
    work_process = multiprocessing.Process(target=work)
 
    work_process.start()
 
    # 让主进程等待1秒钟
    time.sleep(1)
    print(&quot;主进程执行完成了啦&quot;)

</code></pre><p>执行结果：</p>
<pre><code>工作中...
工作中...
工作中...
工作中...
工作中...
主进程执行完成了啦
工作中...
工作中...
工作中...
工作中...
工作中...
</code></pre><p>销毁子进程:terminate()</p>
<pre><code>
import multiprocessing
import time
 
# 测试子进程是否执行完成以后主进程才能退出
def work():
    for i in range(10):
        print(&quot;工作中...&quot;)
        time.sleep(0.2)
 
if __name__ == '__main__':
    # 创建子进程
    work_process = multiprocessing.Process(target=work)
    # 设置守护主进程，主进程退出后子进程直接销毁，不再执行子进程中的代码
    # work_process.daemon = True
    work_process.start()
 
    # 让主进程等待1秒钟
    time.sleep(1)
    print(&quot;主进程执行完成了啦&quot;)
    # 让子进程直接销毁，表示终止执行， 主进程退出之前，把所有的子进程直接销毁就可以了
    work_process.terminate()

</code></pre><p>执行结果:</p>
<pre><code>工作中...
工作中...
工作中...
工作中...
工作中...
主进程执行完成了啦
</code></pre><h1 id="queue">queue</h1>
<p>是一个队列 先put进去的元素会被首先get到</p>
<pre><code>q = Queue(4)
q.put(1)
q.put(2)
q.put(3)
q.put(4)
q.get()
q.get()
q.get()
q.get()
</code></pre><p>执行结果：</p>
<pre><code>1
2
3
4
</code></pre><pre><code>
import multiprocessing
import time
 
if __name__ == '__main__':
    # 创建消息队列, 3:表示队列中最大消息个数
    queue = multiprocessing.Queue(3)
    # 放入数据
    queue.put(1)
    queue.put(&quot;hello&quot;)
    queue.put([3,5])
    # 总结: 队列可以放入任意数据类型
    # 提示： 如果队列满了，需要等待队列有空闲位置才能放入数据，否则一直等待
    # queue.put((5,6))
    # 提示： 如果队列满了，不等待队列有空闲位置，如果放入不成功直接崩溃
    # queue.put_nowait((5,6))
    # 建议： 向队列放入数据统一使用put
 
    # 查看队列是否满了
    # print(queue.full())
 
    # 注意点：queue.empty()判断队列是否空了不可靠
    # 查看队列是否空了
    # print(queue.empty())
 
    # 解决办法: 1. 加延时操作 2. 使用判断队列的个数,不使用empty
    # time.sleep(0.01)
    if queue.qsize() == 0:
        print(&quot;队列为空&quot;)
    else:
        print(&quot;队列不为空&quot;)
 
    # 获取队列的个数
    size = queue.qsize()
    print(size)
 
    # 获取数据
    value = queue.get()
    print(value)
    # 获取队列的个数
    size = queue.qsize()
    print(size)
    # 获取数据
    value = queue.get()
    print(value)
    # 获取数据
    value = queue.get()
    print(value)
 
    # 获取队列的个数
    size = queue.qsize()
    print(size)
 
    # 提示：如果队列空了，再取值需要等待，只有队列有值以后才能获取队列中数据
    # value = queue.get()
    # print(value)
    # 提示： 如果队列空了 ，不需要等待队列有值，但是如果取值的时候发现队列空了直接崩溃
    # 建议大家: 向队列取值使用get
    # value = queue.get_nowait()
    # print(value)
</code></pre><p>运行结果：</p>
<pre><code>队列不为空
3
1
2
hello
[3, 5]
0
</code></pre><p>q = Queue()  # 若括号中没有指定最大可接受的消息数量，或数量为负值
就代表没有上限知道内存的尽头
Queue常用方法:</p>
<ul>
<li>Queue.qsize()：返回当前队列包含的消息数量；</li>
<li>Queue.empty()：如果队列为空，返回True，反之False , 注意这个操作是不可靠的。</li>
<li>Queue.full()：如果队列满了，返回True,反之False；</li>
<li>Queue.get([block[, timeout]])：获取队列中的一条消息，然后将其从列队中移除，block默认值为True；</li>
</ul>
<p>q.get([block[, timeout]])</p>
<ol>
<li>如果block使用默认值，且没有设置timeout（单位秒），消息列队如果为空，
此时程序将被阻塞（停在读取状态），直到从消息列队读到消息为止，如果设置了timeout，
则会等待timeout秒，若还没读取到任何消息，则抛出&quot;Queue.Empty&quot;异常；</li>
<li>如果block值为False，消息列队如果为空，则会立刻抛出&quot;Queue.Empty&quot;异常；
Queue.get_nowait()：相当Queue.get(False)；
Queue.put(item,[block[, timeout]])：将item消息写入队列，block默认值为True；</li>
</ol>
<p>q.put(item,[block[, timeout]])</p>
<ol>
<li>如果block使用默认值，且没有设置timeout（单位秒），消息列队如果已经没有空间可写入，此时程序将被阻塞（停在写入状态），
直到从消息列队腾出空间为止，如果设置了timeout，则会等待timeout秒，若还没空间，则抛出&quot;Queue.Full&quot;异常；</li>
<li>如果block值为False，消息列队如果没有空间可写入，则会立刻抛出&quot;Queue.Full&quot;异常；</li>
</ol>
<ul>
<li>Queue.put_nowait(item)：相当Queue.put(item, False)；</li>
</ul>
<h1 id="进程之间完成通讯">进程之间完成通讯</h1>
<p>创建俩个进程，一个负责写数据,一个负责读数据 实现进程间的通信</p>
<pre><code>
import multiprocessing
import time
 
 
# 写入数据
def write_data(queue):
    for i in range(10):
        if queue.full():
            print(&quot;队列满了&quot;)
            break
        queue.put(i)
        time.sleep(0.2)
        print(i)
 
 
# 读取数据
def read_data(queue):
    while True:
        # 加入数据从队列取完了，那么跳出循环
        if queue.qsize() == 0:
            print(&quot;队列空了&quot;)
            break
        value = queue.get()
        print(value)
 
 
if __name__ == '__main__':
    # 创建消息队列
    queue = multiprocessing.Queue(5)
 
    # 创建写入数据的进程
    write_process = multiprocessing.Process(target=write_data, args=(queue,))
    # 创建读取数据的进程
    read_process = multiprocessing.Process(target=read_data, args=(queue,))
 
    # 启动进程
    write_process.start()
    # 主进程等待写入进程执行完成以后代码再继续往下执行
    write_process.join()
    read_process.start()
</code></pre><p>运行结果：</p>
<pre><code>
0
1
2
3
4
队列满了
0
1
2
3
4
队列空了
</code></pre><h1 id="进程池">进程池</h1>
<p><strong>池子里面放的是进程，进程池会根据任务执行情况自动创建进程，而且尽量少创建进程，合理利用进程池中的进程完成多任务</strong></p>
<p>当需要创建的子进程数量不多时，可以直接利用multiprocessing中的Process动态成生多个进程，但如果是上百甚至上千个目标，手动的去创建进程的工作量巨大，此时就可以用到multiprocessing模块提供的Pool方法。</p>
<p>初始化Pool时，可以指定一个最大进程数，当有新的请求提交到Pool中时，如果池还没有满，那么就会创建一个新的进程用来执行该请求；但如果池中的进程数已经达到指定的最大值，那么该请求就会等待，直到池中有进程结束，才会用之前的进程来执行新的任务.</p>
<p><strong>进程池分为同步执行任务的异步执行任务</strong></p>
<p>同步执行任务：
进程池同步执行任务表示进程池中的进程在执行任务的时候一个执行完成另外一个才能执行，如果没有执行完会等待上一个进程执行</p>
<pre><code>
import multiprocessing
import time
 
# 拷贝任务
def work():
    print(&quot;复制中...&quot;, multiprocessing.current_process().pid)
    time.sleep(0.5)
 
if __name__ == '__main__':
    # 创建进程池
    # 3:进程池中进程的最大个数
    pool = multiprocessing.Pool(3)
    # 模拟大批量的任务，让进程池去执行
    for i in range(5):
        # 循环让进程池执行对应的work任务
        # 同步执行任务，一个任务执行完成以后另外一个任务才能执行
        pool.apply(work)   #同步执行

</code></pre><p>执行结果：</p>
<pre><code>复制中... 100512
复制中... 68128
复制中... 98924
复制中... 100512
复制中... 68128
</code></pre><p>异步执行任务：
进程池异步执行任务表示进程池中的进程同时执行任务，进程之间不会等待</p>
<pre><code># 进程池:池子里面放的进程，进程池会根据任务执行情况自动创建进程，而且尽量少创建进程，合理利用进程池中的进程完成多任务
import multiprocessing
import time
 
 
# 拷贝任务
def work():
    print(&quot;复制中...&quot;, multiprocessing.current_process().pid)
    # 获取当前进程的守护状态
    # 提示：使用进程池创建的进程是守护主进程的状态，默认自己通过Process创建的进程是不是守住主进程的状态
    # print(multiprocessing.current_process().daemon)
    time.sleep(0.5)
 
if __name__ == '__main__':
    # 创建进程池
    # 3:进程池中进程的最大个数
    pool = multiprocessing.Pool(3)
    # 模拟大批量的任务，让进程池去执行
    for i in range(5):
        # 循环让进程池执行对应的work任务
        # 同步执行任务，一个任务执行完成以后另外一个任务才能执行
        # pool.apply(work)
        # 异步执行，任务执行不会等待，多个任务一起执行
        pool.apply_async(work)
 
    # 关闭进程池，意思告诉主进程以后不会有新的任务添加进来
    pool.close()
    # 主进程等待进程池执行完成以后程序再退出
    pool.join()
</code></pre><p>执行结果:</p>
<pre><code>
复制中... 122872
复制中... 61772
复制中... 114636
复制中... 122872
复制中... 114636
</code></pre><h2 id="进程线程对比">进程、线程对比</h2>
<ol>
<li>功能对比
进程，能够完成多任务，比如 在一台电脑上能够同时运行多个QQ
线程，能够完成多任务，比如 一个QQ中的多个聊天窗口</li>
<li>定义对比
进程是系统进行资源分配基本单位，每启动一个进程操作系统都需要为其分配运行资源。
线程是运行程序中的一个执行分支，是CPU调度基本单位。
总结:进程是操作系统资源分配的基本单位，线程是CPU调度的基本单位</li>
<li>关系对比
线程是依附在进程里面的，没有进程就没有线程
一个进程默认提供一条线程，进程可以创建多个线程</li>
<li>区别
进程之间不共享全局变量
线程之间共享全局变量，但是要注意资源竞争的问题，解决办法: 互斥锁或者线程同步
创建进程的资源开销要比创建线程的资源开销要大
进程是操作系统资源分配的基本单位，线程是CPU调度的基本单位
线程不能够独立执行，必须依存在进程中
多进程开发比单进程多线程开发稳定性要强
优缺点
<strong>多进程</strong>：
优点：可以用多核
缺点：资源开销大
<strong>多线程</strong>：
优点：资源开销小
缺点：不能使用多核</li>
</ol>

    </div>
    
      
        <div class="pagination">
          <div class="pagination__title">
            <span class="pagination__title-h">Read other posts</span>
            <hr />
          </div>
          <div class="pagination__buttons">
            
              <span class="button previous">
                <a href="/my_blog/post/py/">
                  <span class="button__icon">←</span>
                  <span class="button__text">python2 和 python3的区别</span>
                </a>
              </span>
            
            
              <span class="button next">
                <a href="/my_blog/post/search/">
                  <span class="button__text">django&#43;vue实现搜索功能</span>
                  <span class="button__icon">→</span>
                </a>
              </span>
            
          </div>
        </div>
      
    


    
      
        

      
    

    </div>

      </div>

      
        <footer class="footer">
  <div class="footer__inner">
    
      <a href="/my_blog/hello/" class="logo" style="text-decoration: none;">
  
    <span class="logo__mark"><svg xmlns="http://www.w3.org/2000/svg" class="greater-icon" viewBox="0 0 44 44">
  <path fill="none" d="M15 8l14.729 14.382L15 35.367"/>
</svg>
</span>
    <span class="logo__text">Welcome To MyBlog</span>
    <span class="logo__cursor"></span>
  
</a>

      <div class="copyright">
        <span>© 2020 Powered by <a href="https://gohugo.io" target="_blank" rel="noopener">Hugo</a></span>
        <span>Theme created by <a href="https://twitter.com/panr" target="_blank" rel="noopener">panr</a></span>
      </div>
    
  </div>
</footer>

<script src="/my_blog/assets/main.js"></script>
<script src="/my_blog/assets/prism.js"></script>


      
    </div>

    
  </body>
</html>
